#include "solver.h"
#include <stdlib.h>

int block_size = 0;
int tile_size = 0;

void parse_env(void) {
  char *p = NULL;

  p = getenv("BLOCK_SIZE");
  if (p)
    block_size = atoi(p);

  p = getenv("TILE_SIZE");
  if (p)
    tile_size = atoi(p);
}

double compute_error(double *x, double *b, int dim) {
  double error = 0;
#pragma omp parallel for
  for (int i = 0; i < dim; i++) {
    error = MAX(error, fabs(x[i] - b[i]));
  }
  return error;
}

int test(int argc, char *argv[]) {
  if (argc < 2) {
    ABORT("Usage: ./test_sparselu filename outputpath\n");
  }
  parse_env();
  MATRIX *A = construct_M();

  // get argv[1] postfix
  char *postfix = strrchr(argv[1], '.');
  if (!strcmp(postfix, ".rb"))
    readrb(argv[1], A);
  else if (!strcmp(postfix, ".csc"))
    readcsc(argv[1], A);
  else
    ABORT("Unknown file format\n");
  // copy argv[2] to A->output_path
  if(argv[2] != NULL){
    A->output_path = (char *)malloc(strlen(argv[2]) + 1);
    strcpy(A->output_path, argv[2]);
    printf("save path %s\n", A->output_path);
  }
  struct timeval tv;
  
  // return -1;

  set_time(&tv);
  get_mc64(A);
  // get_rcm(A);
  get_prcm(A);
  A->reorder_time = get_time(&tv);


  pattern2(A);

  init(A, block_size, tile_size);

  double *x = (double *)calloc(A->real_m, sizeof(double));
  double *b = (double *)calloc(A->real_m, sizeof(double));
  for (int i = 0; i < A->real_m; i++) {
    x[i] = 1.0;
  }
  gemv(A, x, b);

  set_time(&tv);
  dgetrf(A);
  A->fact_time = get_time(&tv);

  set_time(&tv);
  solve(A, b);
  A->solve_time = get_time(&tv);


  double error = compute_error(x, b, A->real_m);
  A->error = error;
  double threshold = 1.0E-3;
  if (error < threshold) {
    printf(GRE "Max error = %e\n" DEF, error);
  } else {
    printf(RED "Max error = %e\n" DEF, error);
  }
  information(A);

  destroy_M(A);
  my_free(x, A->real_m, sizeof(double));
  my_free(b, A->real_m, sizeof(double));
  return 0;
}

int main(int argc, char *argv[]) {
  test(argc, argv);
  return 0;
}
